﻿using System;

namespace Simp.Model.CoreExpressions
{
	/// <summary>Encapsulates an expression computing the power of a number.</summary>
	[ExpressionName("Power")]
	public class PowerExpression : BinaryNumericExpressionBase
	{
		/// <summary>Tries general simplification:  exponent of zero and one.</summary>
		/// <param name="simplificationMode"></param>
		/// <param name="left"></param>
		/// <param name="right"></param>
		/// <returns></returns>
		protected override IExpression Simplify(SimplificationMode simplificationMode, IExpression left, IExpression right)
		{
			IntegerExpression rightInteger = right as IntegerExpression;

			if (rightInteger != null)
			{
				if (rightInteger.Value == 0)
				{
					return new IntegerExpression(1);
				}
				else if (rightInteger.Value == 1)
				{
					return left;
				}
			}

			return base.Simplify(simplificationMode, left, right);
		}

		/// <summary>Performs power.</summary>
		/// <param name="simplificationMode"></param>
		/// <param name="leftInteger"></param>
		/// <param name="leftRational"></param>
		/// <param name="leftReal"></param>
		/// <param name="rightInteger"></param>
		/// <param name="rightRational"></param>
		/// <param name="rightReal"></param>
		/// <returns></returns>
		protected override IExpression SimplifyNumerics(
			SimplificationMode simplificationMode,
			IntegerExpression leftInteger,
			RationalExpression leftRational,
			RealExpression leftReal,
			IntegerExpression rightInteger,
			RationalExpression rightRational,
			RealExpression rightReal)
		{
			if (rightInteger != null && rightInteger.Value > 0 && (leftInteger != null || leftRational != null))
			{	//	Recursively create a product
				IExpression baseToMultiply;

				if (leftInteger != null)
				{
					baseToMultiply = leftInteger;
				}
				else
				{
					baseToMultiply = leftRational;
				}

				IExpression product = baseToMultiply;

				for (int i = 0; i != rightInteger.Value - 1; ++i)
				{
					product = new CompositeExpression(new MultiplicationExpression(), baseToMultiply, product);
				}

				return ExpressionHelper.Simplify(false, product, simplificationMode);
			}
			if (leftReal != null && rightReal != null)
			{
				return new RealExpression(Math.Pow(leftReal.Value, rightReal.Value));
			}

			return null;
		}

		/// <summary>Power isn't commuting.</summary>
		protected override bool IsCommuting
		{
			get { return false; }
		}

		/// <summary>Returns the power symbol.</summary>
		protected override string OperationSymbol
		{
			get { return "^"; }
		}
	}
}